#include"db.hpp"
#include"httplib.h"
#define WWWROOT "./wwwroot"

using namespace httplib;
vod_system::TableVod* tb_vedio;

void VedioDelete(const Request &req,Response &rsp)
{
  ///vedio/plane.mp4
  //req.path = /vedio/1
  //获取视频id
  int vedio_id = std::stoi(req.matches[1]);  //matches[]数组存放的是请求中正则表达式获取到的内容，第0号是全部内容，我们这里使用()获取了视频的id数，所以存放在1
  //从数据库中获取到对应的视频信息
  Json::Value json_rsp;
  Json::Value vedio;
  Json::StyledWriter writer;
  bool ret = tb_vedio->SelectOne(vedio_id,&vedio);
  if(ret == false)
  {
    std::cout<<"VedioDelete error: mysql get vedio info failed!"<<std::endl;
    rsp.status = 500;  //服务器错误
    json_rsp["result"] = false;
    json_rsp["reason"] = "mysql get vedio info failed!";
    rsp.body = writer.write(json_rsp);
    rsp.set_header("Content-Type","application/json");
    return ;
  }
  //删除对应id号的视频文件和图片文件
  std::string vpath = WWWROOT + vedio["vedio_url"].asString();
  std::string ipath = WWWROOT + vedio["image_url"].asString();
  unlink(vpath.c_str());
  unlink(ipath.c_str());
  //删除数据库中的数据
  ret = tb_vedio->Delete(vedio_id);
  if(ret == false)
  {
    rsp.status = 500;
    std::cout<<"mysql get vedio info failed!"<<std::endl;
    return ;
  }
  rsp.status = 200;
}



//这里实现的更新，仅仅支持更新视频描述信息等mysql中的信息，不支持修改视频
void VedioUpdate(const Request &req,Response &rsp)
{
  Json::Value video;
  Json::Reader reader;
  //1.获取视频id
  int video_id = std::stoi(req.matches[1]);
  //2.解析客户端发来的Json字符串(req.body),放在video对象中
  bool ret = reader.parse(req.body,video);
  if(ret == false)
  {
    cout<<"VedioUpdat error: parse video Json failed "<<endl;
    rsp.status = 400;
    return;
  }
  //3.更新mysql数据信息
  ret = tb_vedio->Update(video_id,video);
  if(ret == false)
  {
    cout<<"Update video error: update mysql error " <<endl;
    rsp.status = 500;
    return ;
  }
}




void VedioGetAll(const Request &req,Response &rsp)
{
  //获取所有视频信息
  Json::Value videos;
  Json::FastWriter writer;
  //直接获取mysql信息，包装成Value对象
  bool ret = tb_vedio->SelectAll(&videos);
  if(ret == false)
  {
    cout<<"VedioGetAll error: mysql get failed"<<endl;
    rsp.status = 500;
    return ;
  }
  //将得到的Json对象video进行序列化，放在响应正文
  rsp.body = writer.write(videos);
  //设置正文类型为Json格式的字符串
  rsp.set_header("Content-Type","application/json"); 
}



void VedioGetOne(const Request &req,Response &rsp)
{
  Json::Value video;
  Json::FastWriter writer;
  //1.获取视频id
  int video_id = std::stoi(req.matches[1]);
  //2.根据id获取数据库信息,放在Value对象vedio中
  bool ret = tb_vedio->SelectOne(video_id,&video);
  if(ret == false)
  {
    cout<<"VedioGetOne error: Mysql get error"<<endl;
    rsp.status = 500;
    return ;
  }
  //3.将vedio序列化为字符串放在响应头部
  rsp.body = writer.write(video);
  //4.设置响应正文类型
  rsp.set_header("Content-Type","application/json");
}


//客户端上传文件A，服务端在特定目录下创建文件B，并将A文件的内容写入B文件，更新mysql信息
#define VIDEO_PATH "/video/"
#define IMAGE_PATH "/image/"
void VedioUpload(const Request &req,Response &rsp)
{
  //1.获取视频名称
  bool ret = req.has_file("video_name");
  if(ret == false)
  {
    cout<<"VedidUpload error: has no file"<<endl;
    return;
  }
  const auto& file = req.get_file_value("video_name");

  //2.获取视频描述
  ret = req.has_file("video_desc");
  if(ret == false)
  {
    cout<<"VedidUpload error: has no file"<<endl;
    return;
  }
  const auto& file1 = req.get_file_value("video_desc");

  //3.获取视频文件和视频内容
  const auto& file2 = req.get_file_value("video_file");
  
  cout<<"file2.filename:"<<file2.filename<<endl;
  //4.获取图片文件和图片内容
  const auto& file3 = req.get_file_value("image_file");

  //对视频信息重命名，方便阅读
  const std::string vname = file.content;//                 变形金刚
  const std::string vdesc = file1.content;//                这是一部动作片
  const std::string vfile = std::move(file2.filename);//    **.MP4
  const std::string vcont = std::move(file2.content);//     video content 
  const std::string ifile = std::move(file3.filename);//    **.jpg
  const std::string icont = std::move(file3.content);//     image content

  //5.将文件内容写入到对应文件中
  std::string vurl = VIDEO_PATH + file2.filename;
  std::string iurl = IMAGE_PATH + file3.filename;
  vod_system::Util::WriteFile(WWWROOT + vurl,file2.content);
  vod_system::Util::WriteFile(WWWROOT + iurl,file3.content);

  //6.将文件信息包装成Json::Value对象，插入到mysql中
  Json::Value video;
  video["name"] = vname;
  video["vdes"] = vdesc;
  video["vedio_url"] = vurl;
  video["image_url"] = iurl;
  
  ret = tb_vedio->Insert(video);
  if(ret == false)
  {
    rsp.status = 500;
    cout<<"VideoInsert error: mysql Insert error"<<endl;
    return ;
  }
}

int main()
{
  tb_vedio = new vod_system::TableVod();
  Server srv;
  //正则表达式通常被用来检索、替换符合某个规则的文本
  //这里只要符合是个数字就可以
  //正则表达式\d 匹配一个数字字符   +匹配字符一次或多次
  //R()括号内的内容不会进行特殊字符检查     c++11
  //(d+)，加括号正则表达式表示匹配到内容之后，会对括号的内容进行捕捉，作为一个数据存储在matches数组中
  //      即 正则表达式中 括号代表捕捉
  srv.set_mount_point("/","./wwwroot");
  //srv.set_base_dir("/","./wwwroot");
  srv.Delete(R"(/vedio/(\d+))",VedioDelete);    
  srv.Put(R"(/vedio/(\d+))",VedioUpdate);
  srv.Get(R"(/vedio)",VedioGetAll);
  srv.Get(R"(/vedio/(\d+))",VedioGetOne);
	srv.Post(R"(/vedio)",VedioUpload);
	srv.listen("0.0.0.0",9000);
  return 0;
}

